home *** CD-ROM | disk | FTP | other *** search
/ Delphi 2.0 - Programmer's Utilities Power Pack / Delphi 2.0 Programmer's Utilities Power Pack.iso / s_to_z / tpack / tblretry.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-09-15  |  8.7 KB  |  324 lines

  1. unit TblRetry;
  2. {provides the core table type with retryability for open/edits, plus a pack command
  3. stolen from somewhere, as well as a scan callback feature.}
  4.  
  5. {I could not resist including it in this package as it demonstrates the power of
  6. the retry concept (code for sale) so well. I'm specializing in database apps so I
  7. didn't really give you the works here; that would be another project; but while the
  8. purpose here is to get you to understand the retry idea there are some other concept
  9. buried in this code. enjoy.}
  10.  
  11. interface
  12.  
  13. uses
  14.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  15.   Forms, Dialogs, Grids, DB, DBGrids, dbTables, StdCtrls
  16. , Debug
  17. , PasUtils
  18. , Xtension
  19. , ErrorMsg
  20. , Retry;
  21.  
  22. type
  23.  
  24.   TTableExtendedType = class(TTable)
  25.     cx: TComponentExtensions;
  26.   private
  27.   public
  28.     Constructor Create(aOwner:TComponent); Override;
  29.     Destructor Destroy; Override;
  30.     procedure Loaded; Override;
  31.   published
  32.   end;
  33.  
  34.   TTableWithRetry = class;
  35.   TTableCoreNotifyEvent = procedure(Sender:TTableWithRetry) of object;
  36.  
  37.   TTableWithRetry = class(TTableExtendedType)
  38.   private
  39.     { Private declarations }
  40.     fRetry: TRetry;
  41.     fPostBeforeClose: Boolean; {will try to post before closing if true}
  42.     fHideLinking: Boolean; {will disable linking fields on open.. does not turn on any}
  43.     fWasOpen:Boolean;      {table was open when loaded/last 'retry..'d.}
  44.     fLeaveOpen:Boolean;    {leave table open after first use.}
  45.     fOnScan: TTableCoreNotifyEvent; {called for every record during a scan}
  46.     fOnRetryException: TRetryExceptionEvent;
  47.   protected
  48.     { Protected declarations }
  49.     procedure DoAfterOpen; Override;
  50.     procedure DoBeforeClose; Override;
  51.     procedure DoBeforePost; Override;
  52.     procedure DoOnNewRecord; Override;
  53.     procedure DoRetryOpen(Sender:TObject);
  54.     procedure DoRetryEdit(Sender:TObject);
  55.     procedure RetryException(Sender:TObject;E:Exception;var Action:TExceptionReAction); Virtual;
  56.     function  GetTableFullName:String;
  57.     procedure SetTableFullName(const Value:String);
  58.   public
  59.     { Public declarations }
  60.     constructor Create(AOwner:TComponent); Override;
  61.     destructor Destroy; Override;
  62.     procedure Loaded; Override;
  63.     procedure RetryOpen;
  64.     procedure RetryEdit;
  65.     procedure MayClose;
  66.     procedure Scan;
  67.     procedure Pack;
  68.   published
  69.     { Published declarations }
  70.     property TableFullName: String read GetTableFullName write SetTableFullName stored False;
  71.     property Retry: TRetry read fRetry write fRetry;
  72.     property PostBeforeClose: Boolean read fPostBeforeClose write fPostBeforeClose;
  73.     property HideLinkingKeys: Boolean read fHideLinking write fHideLinking;
  74.     property WasOpen: Boolean  read fWasOpen  write fWasOpen stored false;
  75.     property LeaveOpen: Boolean  read fLeaveOpen  write fLeaveOpen;
  76.     property OnScan: TTableCoreNotifyEvent  read fOnScan  write fOnScan;
  77.     property OnRetryException: TRetryExceptionEvent read fOnRetryException write fOnRetryException;
  78.     end;
  79.  
  80. implementation
  81.  
  82. uses
  83.   dbiprocs
  84.   ,dbitypes
  85.   ,dbierrs;
  86.  
  87. {------------------------------------------------------------------------------}
  88. {                                                                              }
  89. {------------------------------------------------------------------------------}
  90.  
  91. Constructor TTableExtendedType.Create(aOwner:TComponent);
  92. begin
  93.   if (decCreate in DebugFlags) then
  94.     DebugLog(aOwner,'Create '+ClassName+' ('+aOwner.Name+':'+aOwner.ClassName+')');
  95.   inherited Create(aOwner);
  96.   cx:= TComponentExtensions.Create(Self);
  97. end;
  98.  
  99. Destructor TTableExtendedType.Destroy;
  100. begin
  101.   if (decDestroy in DebugFlags) then
  102.     DebugLog(Owner,'Destroy '+ClassName);
  103.   cx.Free;
  104.   inherited Destroy;
  105. end;
  106.  
  107. procedure TTableExtendedType.Loaded;
  108. begin
  109.   if (decLoaded in DebugFlags) then
  110.     DebugLog(Owner,'Loaded '+ClassName);
  111.   inherited Loaded;
  112. end;
  113.  
  114. {------------------------------------------------------------------------------}
  115. {                                                                              }
  116. {------------------------------------------------------------------------------}
  117.  
  118. constructor TTableWithRetry.Create(AOwner:TComponent);
  119. begin
  120.   inherited Create(AOwner);
  121.   fRetry:=TRetry.Create;
  122.   with fRetry do begin
  123.     Interval.Interval:=200;
  124.     Interval.RandomTime:=200;
  125.     OnException:=RetryException;
  126.     end;
  127. end;
  128.  
  129. destructor TTableWithRetry.Destroy;
  130. begin
  131.   fRetry.Free;
  132.   inherited Destroy;
  133. end;
  134.  
  135. procedure TTableWithRetry.Loaded;
  136. begin
  137.   inherited Loaded;
  138.   fWasOpen:=Active;
  139. end;
  140.  
  141. procedure TTableWithRetry.MayClose;
  142. begin
  143.   if (not fWasOpen) or (not fLeaveOpen) then begin
  144.     Close;
  145.     fWasOpen:=Active;
  146.     end;
  147. end;
  148.  
  149. function TTableWithRetry.GetTableFullName:String;
  150. begin
  151.   Result:=TrailingBackSlash(DatabaseName)+TableName;
  152. end;
  153.  
  154. procedure TTableWithRetry.SetTableFullName(const Value:String);
  155. begin
  156.   Active:=False;
  157.   DatabaseName:=ExtractFilePath(Value);
  158.   TableName:=ExtractFileName(Value);
  159. end;
  160.  
  161. {---------------------------------------------------------------------------}
  162.  
  163. procedure TTableWithRetry.RetryException(Sender:TObject;E:Exception;var Action:TExceptionReAction);
  164. begin
  165.   if assigned(fOnRetryException) then
  166.     fOnRetryException(Self,E,Action);
  167. end;
  168.  
  169. procedure TTableWithRetry.RetryOpen;
  170. begin
  171.   if not Active then
  172.     fRetry.RetryAction(DoRetryOpen);
  173. end;
  174. {}
  175. procedure TTableWithRetry.DoRetryOpen(Sender:TObject);
  176. begin
  177.   if not Active then
  178.     Open;
  179. end;
  180.  
  181. procedure TTableWithRetry.RetryEdit;
  182. begin
  183.   if not (State in dsEditModes) then
  184.     fRetry.RetryAction(DoRetryEdit);
  185. end;
  186. {}
  187. procedure TTableWithRetry.DoRetryEdit(Sender:TObject);
  188. begin
  189.   if State<>dsEdit then
  190.     Edit;
  191. end;
  192.  
  193. {---------------------------------------------------------------------------}
  194.  
  195. procedure TTableWithRetry.DoBeforeClose;
  196. begin
  197.   if fPostBeforeClose then
  198.     if State in dsEditModes then
  199.       Post;
  200.   inherited DoBeforeClose;
  201. end;
  202.  
  203. procedure TTableWithRetry.DoAfterOpen;
  204. var
  205.   n:integer;
  206.   a0,a:string;
  207. begin
  208.   inherited DoAfterOpen;
  209.   if fHideLinking then begin
  210.     {hide linking columns}
  211.     a0:=MasterFields+';';
  212.     n:=-1;
  213.     repeat
  214.       SplitString(a0,';',a,a0);
  215.       if a<>'' then begin
  216.         inc(n);
  217.         IndexFields[n].Visible:=False;
  218.         end;
  219.     until a0='';
  220.     end;
  221. end;
  222.  
  223. procedure TTableWithRetry.DoOnNewRecord;
  224. {var
  225.   n:integer;
  226.   a0,a:string;}
  227. begin
  228.   inherited DoOnNewRecord;
  229.   {insert linking values}
  230. {  a0:=MasterFields+';';
  231.   n:=-1;
  232.   repeat
  233.     SplitString(a0,';',a,a0);
  234.     if a<>'' then begin
  235.       inc(n);
  236.       IndexFields[n].Text:=MasterSource.DataSet.FieldByName(a).AsString;
  237.       end;
  238.   until a0='';}
  239. end;
  240.  
  241. procedure TTableWithRetry.DoBeforePost;
  242. begin
  243.   inherited DoBeforePost;
  244. end;
  245.  
  246. {------------------------------------------------------------------------------}
  247. {                                                                              }
  248. {------------------------------------------------------------------------------}
  249.  
  250. procedure TTableWithRetry.Scan;
  251. begin
  252.   try
  253.     RetryOpen;
  254.     First;
  255.     while not eof do begin
  256.       if assigned(fOnScan) then
  257.         fOnScan(Self);
  258.       Next;
  259.       end;
  260.   finally
  261.     MayClose;
  262.     end;
  263. end;
  264.  
  265. {---------------------------------------------------------------------------}
  266.  
  267. procedure TTableWithRetry.Pack;
  268. var
  269.   rslt: DBIResult;
  270.   szErrMsg: DBIMSG;
  271.   pTblDesc: pCRTblDesc;
  272.   bExclusive: Boolean;
  273.   bActive: Boolean;
  274. begin
  275.   {save state}
  276.   bExclusive:=Exclusive;
  277.   bActive:=Active;
  278.   DisableControls;
  279.   Close;
  280.   {begin operation}
  281.   Exclusive := TRUE;
  282.   case TableType of
  283.   ttdBASE: begin
  284.     Open;
  285.     rslt := DbiPackTable( DBHandle, Handle, nil, nil, TRUE);
  286.     if rslt <> DBIERR_NONE then begin
  287.       DbiGetErrorString( rslt, szErrMsg );
  288.       MessageDlg( szErrMsg, mtError, [mbOk], 0 );
  289.       end;
  290.     end;
  291.   ttParadox:
  292.     if MaxAvail < SizeOf(CRTblDesc) then
  293.       MessageDlg('Cannot pack table. Insufficient memory', mtError, [mbOk], 0 )
  294.     else begin
  295.       GetMem(pTblDesc, SizeOf(CRTblDesc) );
  296.       FillChar(pTblDesc^, SizeOf(CRTblDesc), 0 );
  297.       with pTblDesc^ do begin
  298.         StrPCopy(szTblName, TableName );
  299.         StrPCopy(szTblType, szParadox );
  300.         bPack:= TRUE;
  301.         end;
  302.       rslt:= DbiDoRestructure(DBHandle, 1, pTblDesc, nil, nil, nil, FALSE);
  303.       if rslt<>DBIERR_NONE then begin
  304.         DbiGetErrorString(rslt, szErrMsg );
  305.         MessageDlg(szErrMsg, mtError, [mbOk], 0 );
  306.         end;
  307.       FreeMem(pTblDesc, SizeOf(CRTblDesc) );
  308.       end;
  309.   else
  310.     MessageDlg('Cannot pack this table type', mtError, [mbOk], 0 );
  311.     end;
  312.   {restore state}
  313.   Close;
  314.   Exclusive := bExclusive;
  315.   Active := bActive;
  316.   EnableControls;
  317. end;
  318.  
  319.  
  320. end.
  321.  
  322.  
  323.  
  324.